<script setup lang="ts">
import { login, type LoginResponse } from '@/api/login/login'
import { SESSION } from '@/utils/storage'
import { BrowserMultiFormatReader, NotFoundException } from '@zxing/library'

const router = useRouter()

type QrCodeData = {
  medical_record_number: string
  id_last_six: string
}

const showScanner = ref(false)

// 视频流相关
const videoRef = ref<HTMLVideoElement>()
const codeReader = new BrowserMultiFormatReader()
let currentStream: MediaStream | null = null
const isScanning = ref(false)

// 启动视频流
const startVideoStream = async () => {
  if (!videoRef.value) return

  try {
    // 停止当前流
    await stopVideoStream()

    const constraints = {
      video: {
        width: { ideal: 640 },
        height: { ideal: 480 },
        facingMode: 'environment', // 优先使用后置摄像头
      },
    }

    currentStream = await navigator.mediaDevices.getUserMedia(constraints)
    videoRef.value.srcObject = currentStream
    await videoRef.value.play()

    initCameraSuccess.value = true
    startQRScanning()
  } catch (error: any) {
    console.error('启动视频流失败:', error)
    showScanner.value = false
    initCameraSuccess.value = false

    // 处理常见的摄像头错误
    let errorMessage = '摄像头启动失败'
    if (error.name === 'NotAllowedError') {
      errorMessage = '您需要授予相机访问权限'
    } else if (error.name === 'NotFoundError') {
      errorMessage = '未找到可用的摄像头'
    } else if (error.name === 'NotReadableError') {
      errorMessage = '摄像头被其他应用占用'
    } else if (error.name === 'OverconstrainedError') {
      errorMessage = '摄像头不支持所需的配置'
    }

    ElMessage.error(errorMessage)
  }
}

// 停止视频流
const stopVideoStream = async () => {
  if (currentStream) {
    currentStream.getTracks().forEach((track) => track.stop())
    currentStream = null
  }
  if (videoRef.value) {
    videoRef.value.srcObject = null
  }
  isScanning.value = false
  initCameraSuccess.value = false
}

// 开始二维码扫描
const startQRScanning = () => {
  if (!videoRef.value || isScanning.value) return

  isScanning.value = true
  scanQRCode()
}

// 扫描二维码
const scanQRCode = async () => {
  if (!videoRef.value || !isScanning.value) return

  try {
    const result = await codeReader.decodeOnceFromVideoDevice(undefined, videoRef.value)
    if (result && result.getText()) {
      await handleDecode(result.getText())
    }
  } catch (error) {
    if (!(error instanceof NotFoundException)) {
      console.error('二维码扫描错误:', error)
    }
    // 如果仍在扫描，继续尝试
    if (isScanning.value) {
      setTimeout(scanQRCode, 100) // 100ms 后重试
    }
  }
}

// 删除摄像头切换相关函数
const handleShowScanner = async () => {
  showScanner.value = true
  showErrorMsg.value = false
  showSuccessMsg.value = false
  initCameraSuccess.value = false

  // 等待下一个 tick 确保 DOM 已更新
  await nextTick()
  await startVideoStream()
}

interface ResponseMsg extends LoginResponse {
  errorDetails?: {
    type: string
    description: string
  }
}

const responseMsg = ref<ResponseMsg>()

const showSuccessMsg = ref(false)

const showErrorMsg = ref(false)

const handleDecode = async (data: string) => {
  closeScanner()
  const params = JSON.parse(data) as QrCodeData
  try {
    const response = await login(params)
    if (response.payload) {
      SESSION.set('user_info', response.payload.user_info)
      SESSION.set('is_admin', response.payload.is_admin)
      SESSION.set('access_token', response.payload.access_token)
      const timer = setTimeout(() => {
        clearTimeout(timer)
        router.push('/')
      }, 3 * 1000)
      responseMsg.value = response
      showSuccessMsg.value = true
    }
  } catch (error: any) {
    responseMsg.value = error
    showErrorMsg.value = true
  }
}

const closeScanner = async () => {
  showScanner.value = false
  await stopVideoStream()
}

const initCameraSuccess = ref(false)

// 页面卸载时清理资源
onUnmounted(async () => {
  await stopVideoStream()
  codeReader.reset()
})
</script>

<template>
  <div class="h-full bg-#F5F5F5 flex items-center justify-center overflow-auto">
    <div class="w-120 bg-white p-10 rounded-lg shadow-lg">
      <h1 class="text-3xl font-bold text-center">二维码登录</h1>
      <el-button
        v-if="!showScanner"
        type="primary"
        class="w-full mt-8 py-6!"
        @click="handleShowScanner"
      >
        启动摄像头扫描
      </el-button>
      <el-button v-else type="danger" class="w-full mt-4 py-6!" @click="closeScanner">
        停止扫描
      </el-button>

      <div
        v-if="showScanner"
        :class="['flex justify-center mt-8 w-auto', initCameraSuccess ? 'h-90' : 'h-0']"
      >
        <div class="video-container relative">
          <video
            ref="videoRef"
            class="w-full h-full object-cover"
            autoplay
            muted
            playsinline
          ></video>
          <div v-if="initCameraSuccess" class="qr-scanner-container">
            <div class="qr-scanner">
              <div class="mask-top"></div>
              <div class="mask-bottom"></div>
              <div class="mask-left"></div>
              <div class="mask-right"></div>
              <div class="box">
                <div class="line"></div>
                <div class="angle"></div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div v-if="showSuccessMsg" class="mt-8 result success">
        <h3>✅ 登录成功！</h3>
        <p><strong>Token:</strong> {{ responseMsg?.payload?.access_token.substring(0, 50) }}...</p>
        <p>
          <strong>用户类型:</strong>
          {{ String(responseMsg?.payload?.is_admin) === 'true' ? '管理员' : '普通用户' }}
        </p>
        <p><strong>消息:</strong> {{ responseMsg?.message }}</p>
        <p><strong>病历号:</strong> {{ responseMsg?.payload?.user_info?.medical_record_number }}</p>
      </div>
      <div v-if="showErrorMsg" class="mt-8 result error">
        <h3>❌ 登录失败</h3>
        <p>
          <strong>错误信息:</strong>
          {{ responseMsg?.errorDetails?.description || responseMsg?.message || '未知错误' }}
        </p>
        <p><strong>状态码:</strong> {{ responseMsg?.code }}</p>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
$boxWidth: 220px;
$boxHeight: 220px;

.video-container {
  position: relative;
  width: 100%;
  max-width: 640px;
  height: 360px;
}

.qr-scanner-container {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.qr-scanner {
  background-size: 3rem 3rem;
  background-position: -1rem -1rem;
  width: 100%;
  height: 100%;
  position: relative;
  z-index: 1;
}

/* 四个遮罩层 */
.mask-top {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: calc(50% - $boxHeight / 2);
  background-color: #0000007a;
  z-index: 2;
}

.mask-bottom {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: calc(50% - $boxHeight / 2);
  background-color: #0000007a;
  z-index: 2;
}

.mask-left {
  position: absolute;
  top: calc(50% - $boxHeight / 2);
  left: 0;
  width: calc(50% - $boxWidth / 2);
  height: $boxHeight;
  background-color: #0000007a;
  z-index: 2;
}

.mask-right {
  position: absolute;
  top: calc(50% - $boxHeight / 2);
  right: 0;
  width: calc(50% - $boxWidth / 2);
  height: $boxHeight;
  background-color: #0000007a;
  z-index: 2;
}

.qr-scanner .box {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: $boxWidth;
  height: $boxHeight;
  overflow: hidden;
  background-color: transparent;
  z-index: 3;
}

.qr-scanner .box::before {
  content: '';
  position: absolute;
  top: -4px;
  left: -4px;
  right: -4px;
  bottom: -4px;
  z-index: -1;
}

.qr-scanner .box:after,
.qr-scanner .box:before,
.qr-scanner .angle:after,
.qr-scanner .angle:before {
  content: '';
  display: block;
  position: absolute;
  width: 3vw;
  height: 3vw;

  border: 0.2rem solid transparent;
}

.qr-scanner .box:after,
.qr-scanner .box:before {
  top: 0;
  border-top-color: #fff;
  border-width: 4px;
}

.qr-scanner .angle:after,
.qr-scanner .angle:before {
  bottom: 0;
  border-bottom-color: #fff;
  border-width: 4px;
}

.qr-scanner .box:before,
.qr-scanner .angle:before {
  left: 0;
  border-left-color: #fff;
  border-width: 4px;
}

.qr-scanner .box:after,
.qr-scanner .angle:after {
  right: 0;
  border-right-color: #fff;
  border-width: 4px;
}

/* 结果消息样式 */
.result {
  padding: 16px;
  border-radius: 8px;
  border: 1px solid;

  h3 {
    margin: 0 0 12px 0;
    font-size: 18px;
    font-weight: bold;
  }

  p {
    margin: 8px 0;
    line-height: 1.5;

    strong {
      font-weight: 600;
    }
  }
}

.result.success {
  background-color: #f0f9ff;
  border-color: #22c55e;
  color: #065f46;

  h3 {
    color: #059669;
  }
}

.result.error {
  background-color: #fef2f2;
  border-color: #ef4444;
  color: #991b1b;

  h3 {
    color: #dc2626;
  }
}
</style>
